#pragma once


class CLampSound    //  Receiver
{
public:
    CLampSound() { }
    virtual ~CLampSound() { }

public:
    void TurnOn()
    {
        cout << "Sound ON" << endl;
    }

    void TurnOff()
    {
        cout << "Sound OFF" << endl;
    }
};

class CLampSoundNoCmd : public ICmd     //  ConcreteCommand
{
public:
    CLampSoundNoCmd() { }
    virtual ~CLampSoundNoCmd() { }

public:
    virtual void Exec() { }
    virtual void Undo() { }
};

class CLampSoundOnCmd : public ICmd     //  ConcreteCommand
{
    CLampSound* m_lpLampSound;

    CLampSoundOnCmd() { }

public:
    CLampSoundOnCmd(CLampSound* lpFlashLamp) : m_lpLampSound(lpFlashLamp) { }
    virtual ~CLampSoundOnCmd() { }

public:
    virtual void Exec()
    {
        m_lpLampSound->TurnOn();
    }

    virtual void Undo()
    {
        m_lpLampSound->TurnOff();
    }
};

class CLampSoundOffCmd : public ICmd     //  ConcreteCommand
{
    CLampSound* m_lpLampSound;

    CLampSoundOffCmd() { }

public:
    CLampSoundOffCmd(CLampSound* lpFlashLamp) : m_lpLampSound(lpFlashLamp) { }
    virtual ~CLampSoundOffCmd() { }

public:
    virtual void Exec()
    {
        m_lpLampSound->TurnOff();
    }

    virtual void Undo()
    {
        m_lpLampSound->TurnOn();
    }
};

class CMarcoCmd : public ICmd
{
    list<ICmd*> m_CmdList;

public:
    CMarcoCmd() { }
    virtual ~CMarcoCmd() { }

public:
    void Push(ICmd* lpCmd)
    {
        m_CmdList.push_back(lpCmd);
    }

public:
    virtual void Exec()
    {
        for (auto it = m_CmdList.begin(); it != m_CmdList.end(); ++it)
        {
            (*it)->Exec();
        }
    }

    virtual void Undo()
    {
        for (auto it = m_CmdList.begin(); it != m_CmdList.end(); ++it)
        {
            (*it)->Undo();
        }
    }
};